package com.icoolkj.ms.rbac.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author icoolkj
 * @version 1.0
 * @description
 * @createDate 2025/02/17 11:48
 */
@Aspect
@Component
public class CacheKeyAspect {

    @Before("@annotation(org.springframework.cache.annotation.Cacheable)")
    public void beforeCacheableMethod(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Cacheable cacheable = method.getAnnotation(Cacheable.class);
        String[] cacheNames = cacheable.cacheNames();
        String keyExpression = cacheable.key();

        // 解析 SpEL 表达式获取 key
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();
        Object[] args = joinPoint.getArgs();
        String[] parameterNames = signature.getParameterNames();
        for (int i = 0; i < parameterNames.length; i++) {
            context.setVariable(parameterNames[i], args[i]);
        }
        Object key = parser.parseExpression(keyExpression).getValue(context);

        System.out.println("Cache names: " + String.join(", ", cacheNames));
        System.out.println("Cache key: " + key);
    }
}